このnotebookでは、これまでに学んだテクニックの全てを駆使して、暗号化されたモデルと暗号化されたデータを使ってニューラルネットワークのトレーニング、そして推論をを行います。
特に、暗号化されたデータを使って微分を計算できる、"Autograd Engine"について紹介します。
Authors:
In [ ]:
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import syft as sy
In [ ]:
# Set everything up
hook = sy.TorchHook(torch)
alice = sy.VirtualWorker(id="alice", hook=hook)
bob = sy.VirtualWorker(id="bob", hook=hook)
james = sy.VirtualWorker(id="james", hook=hook)
In [ ]:
# A Toy Dataset
data = torch.tensor([[0,0],[0,1],[1,0],[1,1.]])
target = torch.tensor([[0],[0],[1],[1.]])
# A Toy Model
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.fc1 = nn.Linear(2, 2)
self.fc2 = nn.Linear(2, 1)
def forward(self, x):
x = self.fc1(x)
x = F.relu(x)
x = self.fc2(x)
return x
model = Net()
暗号化は2つのステップで実行されます。ステップ1では、"Secure Multi-Party Computation"が整数でしか動作しないため、"Fixed Precision"を使って不動小数点型のオブジェクトを整数型にエンコードしますy。これは.fix_precision()
で実現できます。
ステップ2では、.share()
を使ってデータを実際に暗号化します。この例ではshares
をAliceとBobに分割して送信してします。
こので注意すべき点はrequires_gradプロパティをTrueにセットしておくことです。こうしておくことで暗号化されたデータに対してもautogradが適用できるようになります。実をいうと、"Secure Multi-Party Computation"は整数でしか動きませんが、PyTorchデフォルトのautogradは不動少数でしか動きません。そのため、私たちは特別なAutogradTensorを自作する必要がありました。print
関数を使えば各エレメントにAutogradTensorが含まれているかどうか確認できますよ。
In [ ]:
# 全て暗号化しておきます
data = data.fix_precision().share(bob, alice, crypto_provider=james, requires_grad=True)
target = target.fix_precision().share(bob, alice, crypto_provider=james, requires_grad=True)
model = model.fix_precision().share(bob, alice, crypto_provider=james, requires_grad=True)
In [ ]:
print(data)
In [ ]:
opt = optim.SGD(params=model.parameters(),lr=0.1).fix_precision()
for iter in range(20):
# 1) 前回の微分の計算結果をクリアしておきます。(もしあれば)
opt.zero_grad()
# 2) 予測を行います
pred = model(data)
# 3) ロスを計算します
loss = ((pred - target)**2).sum()
# 4) 勾配ベクトルを計算します
loss.backward()
# 5) モデルのウェイトを更新します
opt.step()
# 6) 確認のため、状況を出力します
print(loss.get().float_precision())
ロスはちゃんと下がっていますね。
モデルからデータまで、全てを暗号化してしまって、トレーニングに影響は無いのか、期待通りロスが下がるのか、気になりますよね。でも、暗号化はされていても、行われているコンピューテーションは、理論上は、同じです。実際、暗号化環境下でのトレーニングも通常のトレーニングも結果はほぼ同じです。同じモデルを同じデータで暗号化せずにトレーニングしてみてください。その際には初期値にを固定して、同じものを使う必要があります。
モデルを初期化したい場合は、例えば、__init__
の中で:
with torch.no_grad():
self.fc1.weight.set_(torch.tensor([[ 0.0738, -0.2109],[-0.1579, 0.3174]], requires_grad=True))
self.fc1.bias.set_(torch.tensor([0.,0.1], requires_grad=True))
self.fc2.weight.set_(torch.tensor([[-0.5368, 0.7050]], requires_grad=True))
self.fc2.bias.set_(torch.tensor([-0.0343], requires_grad=True))
を実行してみてください。
気がついたかもしれませんが、唯一の違いは"fixed precision"を使って少数を整数に変更したり、整数を少数に戻したりする時に誤差が生じるということです。デフォルトのprecision_fractional
の値は3です。この値を2にすると誤差は大きくなります。もし、誤差をさらに小さくしたい場合はprecision_fractional = 4
を試してみても良いかもしれません。
本チュートリアルを完了しました。おめでとうございます!もし、このチュートリアルを気に入って、プライバシーに配慮した非中央集権的なAI技術や付随する(データやモデルの)サプライチェーンにご興味があって、プロジェクトに参加したいと思われるなら、以下の方法で可能です。
一番簡単に貢献できる方法はこのGitHubのレポジトリにスターを付けていただくことです。スターが増えると露出が増え、より多くのデベロッパーにこのクールな技術の事を知って貰えます。
最新の開発状況のトラッキングする一番良い方法はSlackに入ることです。 下記フォームから入る事ができます。 http://slack.openmined.org
コミュニティに貢献する一番良い方法はソースコードのコントリビューターになることです。PySyftのGitHubへアクセスしてIssueのページを開き、"Projects"で検索してみてください。参加し得るプロジェクトの状況を把握することができます。また、"good first issue"とマークされているIssueを探す事でミニプロジェクトを探すこともできます。
もし、ソースコードで貢献できるほどの時間は取れないけど、是非何かサポートしたいという場合は、寄付をしていただくことも可能です。寄附金の全ては、ハッカソンやミートアップの開催といった、コミュニティ運営経費として利用されます。
In [ ]: